Lists

The list data-type is a way in which we can store a collection of objects; we can store numbers, strings, and even we can even store lists within lists within lists.

And, as normal, there are two basic ways to create a list.

The first way:

[ {item1}, {item2}, {...} ]

So basically, we type an opening square bracket "[" any number of items (separated by a comma) and a closing square bracket "]" and we are done. Simple huh?

A few examples...


In [1]:
a = []                      # empty list
b = [True]                  # single item, a boolean
c = [1, 2, 3, 4]            # list of 4 numbers
d = ["a", 2, "b", 4]        # strings and numbers
e = [ [1,2], [2,3], [3,2]]  # lists within lists

print(a,b,c,d,e, sep="\n")

# Also, if you want to create a list of size n with the same value you can use the "*" operator

#    [{value}] * {n}

f = [True]  * 6   # sequence True, True, ...
g = [1,2]   * 3   # sequence 1,2,1,2 ...
h = [[1,2]] * 3   # sequence [1,2],[1,2], ...

print("", f,g,h, sep="\n")


[]
[True]
[1, 2, 3, 4]
['a', 2, 'b', 4]
[[1, 2], [2, 3], [3, 2]]

[True, True, True, True, True, True]
[1, 2, 1, 2, 1, 2]
[[1, 2], [1, 2], [1, 2]]

The list function

The other way to make lists is call the 'list' function with a valid argument. for example:


In [129]:
a = "this is a string"
b = (1,2,3,4,5)       # this is a tuple of integers
c = range(1, 6)       # range object, a built in function

print(list(a), list(b), list(c), sep="\n")


['t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g']
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]

Other ways to make lists...

So, we can just make lists with the '[]' syntax, or we can call the 'list' built-in. It is also worth noting that some other data-types have methods that return lists as well.

The string method "split" is a really good example. We give it a string and the split method chops it up into parts. It then takes those parts and creates a list out of those parts. The split method has an optional argument called "sep" which defaults to spaces, " ", if not give a value.

Lets watch it in action!


In [1]:
cool_story_bro = "The big brown ugly fox jumped into a lampost; I have no idea why."

print(cool_story_bro.split())     # By default split works on with " ". Which means a list of words will be returned. 
print(cool_story_bro.split(";"))  # Here we split on a semi-colon...
print( cool_story_bro.split("a")) # Here we split on the letter a.


['The', 'big', 'brown', 'ugly', 'fox', 'jumped', 'into', 'a', 'lampost;', 'I', 'have', 'no', 'idea', 'why.']
['The big brown ugly fox jumped into a lampost', ' I have no idea why.']
['The big brown ugly fox jumped into ', ' l', 'mpost; I h', 've no ide', ' why.']

Take care to note that the split method 'consumes' the character it is splitting on. If you look at the above three examples you should notice that the lists don’t contain that character; the word list contains no spaces, the colon list contains no semi-colons and the "a" list has no "a" characters in it!

Split is a method I end up using a lot, it is frequently useful for parsing strings into data that is easier to use. For example, in the first strings lecture we were working with the following directory:

"C:\Documents\pictures\selfies\nudes\tasteful.jpeg" 

With split, its really easy to extract the filename (and this should work for all directories):


In [2]:
directory =  r"C:\Documents\pictures\selfies\nudes\tasteful.jpeg"  # note, using r"{string}" here...
dir_parts = directory.split("\\") # remember '\' is an escape character!

print ("The filename is...", dir_parts[-1])


The filename is... tasteful.jpeg

Okay, so thats several ways we can make lists covered, now lets look at a few ways we can play with lists once they are built!

Adding to lists...

So you have a list and you want to add values to it, how does one do that? The answer to that questions depends on:

  1. What you want to add?
  2. How you want that value stored?
  3. Do you want to make a new list, or change the current list?

If we have two lists, we can just use the "+" command. like so:


In [131]:
a = [1,2]
b = [7,9]
c = []

print(a + b + c)
print(c + b + a)


[1, 2, 7, 9]
[7, 9, 1, 2]

I'd like to make two brief notes here; firstly, adding lists to lists (unlike numbers to numbers) does not have the commutative property. This means a + b is not the same as b + a. And this is why you need to be careful with ‘operator overloading’; just because you see the same symbol being used does not mean we are simply doing addition!

Secondly, I'd like to point out that we are creating a new list here, the original lists have not changed. If we want to add list b and list c to list a then we have to do things a little differently...


In [4]:
a = [1,2]
b = [3,4]
c = [5]

print(a)                 # <= before we change it. 
a += b + c               # += is shorthand for writing; a = a + b + c

print(a, b, c, sep="\n")


[1, 2]
[1, 2, 3, 4, 5]
[3, 4]
[5]

The "+=" syntax basically makes a new list (containing a, b, c) but then assigns that list to the name 'a'. Notice that when we print lists b, c they are unchanged in this process but list 'a' is now [1,2,3,4,5] when it used to be just [1,2].

However, lets suppose this is not the behaviour you actually wanted. what if you want a list of lists?


In [5]:
a = [1, 2]
b = [7,9]
c = [] 

# Method #1: 
# Just make a new list by typing out what you want, this DOES NOT change the intial lists.
print([a, b, c])
print([c, b, a])

# Method #2: Updating a...
a = [a, b, c]
print("\nUsing 'a' equals...     :", a)

# Note that if we add b, c to a the result is slightly different:
a = [1,2] # reseting a

a += [b, c]
print("Using 'a' plus equals...:", a)


[[1, 2], [7, 9], []]
[[], [7, 9], [1, 2]]

Using 'a' equals...     : [[1, 2], [7, 9], []]
Using 'a' plus equals...: [1, 2, [7, 9], []]

Notice the difference in the last two cases. If we say a = [a,b,c] then we set a to equal a list of three lists. Whereas in the second case list a has the numbers 1, 2 and then two lists at the end.

You may have noticed that everything we have discussed thus far has us adding lists to other lists, what if we want to add other data-types, such as numbers or strings? In this case we need append.

Append can be used to add also sorts of values to lists, boolean, integers, floats, strings, to name a few. Please note that append always adds things to the end of the list (the reason Python adds values to the end and not at the beginning is a bit technical, but basically, adding to the end is more efficient). Here are a few examples...


In [134]:
lst = [1, 2, 3]
lst.append(4)               # Integer
lst.append(63.979696)       # Float
lst.append(True)            # Boolean
print(lst)


[1, 2, 3, 4, 63.979696, True]

In the case of iterables, however you are going to what to think about the behaviour you want; If I have the string "abc" do I want to add the whole thing or do I want to add all the individual elements (i.e. 'a', 'b', 'c') to the list.

If you want a single value to added to the list use append just as before. If you want each element in the list we need a new method, extend. For example:


In [135]:
a = ["x", "y"]
b = a[:] # [:] creates a 'shallow copy' of a
a.append("abc")
b.extend("abc")
print("Append 'abc':", a, "\nExtend 'abc':", b)


Append 'abc': ['x', 'y', 'abc'] 
Extend 'abc': ['x', 'y', 'a', 'b', 'c']

And since lists are also iterables, append/extend works on them as well:


In [136]:
a = ["x", "y"]
b = a[:] # <== I will explain what this does in the index/slice lecture!
a.append(["a", "b", "c"])
b.extend(["a", "b", "c"])
print("Append 'abc':", a, "\nExtend 'abc':", b)


Append 'abc': ['x', 'y', ['a', 'b', 'c']] 
Extend 'abc': ['x', 'y', 'a', 'b', 'c']

Alright, so that should just about cover everything you need concerning adding stuff to lists. Next up; removing stuff.

Removing elements

Compared to adding stuff to lists, removing things is a bit simpler, there are two basic ways to do it...

remove method

The remove method does exactly what is says, you give this function something to look such for and then it removes the first instance it finds. If that value isn't found, an error is returned. Allow me to demonstrate:


In [137]:
a = [1, 2, 1, 3]
print("start", a)
a.remove(1)
print("1:------", a)
a.remove(1)
print("2:---------", a)
a.remove(1) # no 1's are left, error!


start [1, 2, 1, 3]
1:------ [2, 1, 3]
2:--------- [2, 3]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-137-655a1df0addf> in <module>()
      5 a.remove(1)
      6 print("2:---------", a)
----> 7 a.remove(1) # no 1's left, error!

ValueError: list.remove(x): x not in list

Pop method

The pop method does two things, first it removes the item from the list, and second it returns that item. By default, pop will remove the last item in this list, but if you give it an index (more on indexing later), it can 'pop' something from any position. For example:


In [6]:
lst = ["first", "middle", "last"]
item = lst.pop() # item now is assigned to "last". Last is removed from list.
print("item is '{}'".format(item), "lst is {}".format(lst), sep="\n")  

item_2 = lst.pop(0) # index 0 is the first item
print("\nitem_2 is '{}'".format(item_2), "lst is {}".format(lst), sep="\n")


item is 'last'
lst is ['first', 'middle']

item_2 is 'first'
lst is ['middle']

Conclusion

Okay, so this a very broad over-view of lists, but one of the most powerful features of lists is that they can in indexed into, which is the subject of the next lecture, so stay tuned for that.